package com.yunhe.common.tempcache;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.AbstractMap;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Map;

import java.util.Set;

/**
 * @ClassName CacheMap
 * @Description TODO
 * @Author HeTao
 * @Date 2021/3/17 15:42
 * @Version 1.0
 **/
public class CacheMap<K,V> extends AbstractMap<K,V> {
    private static final long DEFAULT_TIMEOUT = 10*60*1000;

    private static CacheMap defaultInstance;

    public static synchronized final CacheMap getDefault() {
        if (defaultInstance == null) {
            defaultInstance = new CacheMap(DEFAULT_TIMEOUT);
        }

        return defaultInstance;

    }

    private class CacheEntry implements Entry<K,V>{
        long time;
        V value;
        K key;

        CacheEntry(K key, V value) {
            super();

            this.value = value;

            this.key = key;

            this.time = System.currentTimeMillis();

        }

        @Override
        public K getKey() {
            return key;

        }

        @Override
        public V getValue() {
            return value;

        }

        @Override
        public V setValue(V value) {
            return this.value = value;

        }

    }

    private class ClearThread extends Thread {
        private  Logger logger = LoggerFactory.getLogger(ClearThread.class);
        ClearThread() {
            setName("clear cache map thread");
        }
        @Override
        public void run() {
            logger.info("清空前map的长度{}"+map.size());
            while (true) {
                try {
                    long now = System.currentTimeMillis();
                    Object[] keys = map.keySet().toArray();
                    for (Object key : keys) {
                        CacheEntry entry = (CacheEntry) map.get(key);
                        if (now - entry.time >= cacheTimeout) {
                            synchronized (map) {
                                map.remove(key);
                            }
                        }
                    }
                    Thread.sleep(cacheTimeout);
                    logger.info("清空后map的长度{}"+map.size());
                } catch (Exception e) {
                    e.printStackTrace();

                }

            }

        }
    }

    private long cacheTimeout;

    private Map map = new HashMap();

    public CacheMap(long timeout) {
        this.cacheTimeout = timeout;
        new ClearThread().start();
    }



    @Override
    public V get(Object key) {
        CacheEntry entry = (CacheEntry) map.get(key);
        return entry == null ? null : entry.value;

    }

    @Override
    public Set entrySet() {
        Set<Entry>  entrySet = new HashSet<Entry>();

        Set<Entry>  wrapEntrySet = map.entrySet();

        for (Entry entry : wrapEntrySet) {
            entrySet.add((Entry) entry.getValue());

        }
        return entrySet;
    }

    @Override
    public V put(K key, V value) {
        CacheEntry entry = new CacheEntry(key, value);
        synchronized (map) {
            map.put(key, entry);
        }
        return value;
    }

}
